package org.jground.rx.ui.zk.viewControl;

import java.util.HashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jground.rx.RXAttribute;
import org.jground.rx.RXControl;
import org.jground.rx.RXType;
import org.jground.rx.RXView;
import org.jground.rx.ui.IUIAttributeControl;
import org.jground.rx.ui.IUIAttributeView;
import org.jground.rx.ui.zk.UIFrame;
import org.jground.util.L;
import org.jground.util.StringUtils;
import org.zkoss.zk.ui.Component;

public class UIAttributeViewControlFactory {

    private static Log logger = LogFactory.getLog(UIAttributeViewControlFactory.class);

    private static HashMap<String, IUIAttributeView<Component,UIFrame>> viewFactories = new HashMap<String, IUIAttributeView<Component,UIFrame>>();
    private static HashMap<String, IUIAttributeControl<Component,UIFrame>> controlFactories = new HashMap<String, IUIAttributeControl<Component,UIFrame>>();

    public static void registerViewFactory(String key, IUIAttributeView<Component,UIFrame> createMethod) {
        viewFactories.put(key, createMethod);
    }

    public static void registerControlFactory(String key, IUIAttributeControl<Component,UIFrame> createMethod) {
        controlFactories.put(key, createMethod);
    }

    public static void register(String registerString) {
        String name = null;
        String className = null;
        try {
            String[] values = StringUtils.split(registerString, '*');
            if (values.length==2) {
                name = values[0];
                className = values[1];
            } else {
                className = registerString;
            }
            Object obj = Class.forName(className).newInstance();
            if (name != null) {
                if (obj instanceof IUIAttributeControl<?,?>) {
                    registerControlFactory(name, (IUIAttributeControl<Component,UIFrame>) obj);
                    logger.info("register widgetHint : " + name + " for control " + className);
                } else if (obj instanceof IUIAttributeView<?,?>) {
                    registerViewFactory(name, (IUIAttributeView<Component,UIFrame>) obj);
                    logger.info("register widgetHint : " + name + " for view " + className);
                }
            } else {
                logger.info("register " + className);
            }
        } catch (Exception e) {
            logger.error(e, e);
        }
    }

    static {

        // CONTROLs
        controlFactories.put(RXType.STRING, new UIAttributeControlString());
        controlFactories.put(RXType.TEXT, new UIAttributeControlString());
        controlFactories.put(RXType.HTMLTEXT, new UIAttributeControlHtmltext());
        controlFactories.put(RXType.INTEGER, new UIAttributeControlString());
        controlFactories.put(RXType.FLOAT, new UIAttributeControlString());
        controlFactories.put(RXType.BOOLEAN, new UIAttributeControlBoolean());
        controlFactories.put(RXType.PERCENTAGE, new UIAttributeControlString());
        controlFactories.put(RXType.DATE, new UIAttributeControlString());
        controlFactories.put(RXType.DATETIME, new UIAttributeControlString());
        controlFactories.put(RXType.TIME, new UIAttributeControlString());
        controlFactories.put(RXType.CODETABLE, new UIAttributeControlCodetable());
        controlFactories.put(RXType.CURRENCY, new UIAttributeControlCurrency());
        controlFactories.put(RXType.REF, new UIAttributeControlRef());
        controlFactories.put(RXType.COMPONENT, new UIAttributeControlComponent());
        controlFactories.put(RXType.FOREACH, new UIAttributeControlForeach());

        // VIEWs
        viewFactories.put(RXType.VALUES, new UIAttributeViewString());
        viewFactories.put(RXType.STRING, new UIAttributeViewString());
        viewFactories.put(RXType.TEXT, new UIAttributeViewString());
        viewFactories.put(RXType.HTMLTEXT, new UIAttributeViewHtmltext());
        viewFactories.put(RXType.INTEGER, new UIAttributeViewString());
        viewFactories.put(RXType.FLOAT, new UIAttributeViewString());
        viewFactories.put(RXType.BOOLEAN, new UIAttributeViewString());
        viewFactories.put(RXType.PERCENTAGE, new UIAttributeViewString());
        viewFactories.put(RXType.DATE, new UIAttributeViewString());
        viewFactories.put(RXType.DATETIME, new UIAttributeViewString());
        viewFactories.put(RXType.TIME, new UIAttributeViewString());
        viewFactories.put(RXType.CODETABLE, new UIAttributeViewCodetable());
        viewFactories.put(RXType.CURRENCY, new UIAttributeViewCurrency());
        viewFactories.put(RXType.COMPONENT, new UIAttributeViewComponent());
        viewFactories.put(RXType.REF, new UIAttributeViewRef());
        viewFactories.put(RXType.BACK_REF, new UIAttributeViewBackref());
        viewFactories.put(RXType.FOREACH, new UIAttributeViewForeach());

    }

    public static IUIAttributeView<Component,UIFrame> create(UIFrame uiFrame, RXView moView) {
        RXAttribute moAttribute = moView.getRXAttribute();
        String name = moAttribute.getRXType().getBaseType().getTypeId();
        String widgetHint = moView.getWidgetHint();
        name = widgetHint != null ? widgetHint : name;
        L.debug(logger, "try to create AttributeControl ", name);
        IUIAttributeView<Component,UIFrame> viewControl = null;
        if (moView instanceof RXControl) {
            if (controlFactories.containsKey(name)) {
                return controlFactories.get(name).createNew(uiFrame, (RXControl) moView);
            } else {
                logger.error("No control found for " + name);
                viewControl = new UIViewControlDummy().createNew(uiFrame, moView);
            }
        } else {
            if (viewFactories.containsKey(name)) {
                return viewFactories.get(name).createNew(uiFrame, moView);
            } else {
                logger.error("No view found for " + name);
                viewControl = new UIViewControlDummy().createNew(uiFrame, moView);
            }
        }
        return viewControl;
    }
}